package com.sxyjhh.utils.util.wsUtil;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.tomcat.util.codec.binary.Base64;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class EncryptUtil {
	//异或加密
	//private static final Logger log = LogManager.getLogger(EncryptUtil.class);
	static String xorEncryptKey = "p0asdjfi;adsfj23i9a@#$%^&*()";

	/**
	 * 使用默认密钥对字符串进行异或加密
	 * @param _value 字符串
	 * @return 返回处理过的字符串
	 */
	private static String XorEncrypt(String _value) {
		return XorEncrypt(_value, xorEncryptKey);
	}
	/**
	 * 使用指定密钥对字符串进行异或加密
	 * @param _value 字符串
	 * @param _key key
	 * @return 返回处理过的字符串
	 */
	private static String XorEncrypt(String _value, String _key) {
		// 参数检查
		if (StringUtils.isBlank(_value))
		    System.out.println("传入加密的字符串不能为空");
		if (StringUtils.isBlank(_key))
            System.out.println("传入加密的密钥不能为空");

		StringBuilder stringBuilder = new StringBuilder();

		// 逐个字符异或
		for (int i = 0; i < _value.length(); i++) {
			char c = (char) (_value.charAt(i) ^ _key.charAt(i % _key.length()));
			stringBuilder.append(c);
		}
		return stringBuilder.toString();
	}

	/**
	 * 返回字符串的MD5摘要信息
	 * @param _value
	 * @return 返回字符串的MD5摘要信息
	 * @throws NoSuchAlgorithmException
	 * @throws UnsupportedEncodingException
	 */
	private static String makeMD5Digest(String _value)throws NoSuchAlgorithmException, UnsupportedEncodingException {
		// 参数检查
		if (StringUtils.isBlank(_value))
            System.out.println("传入加密的字符串不能为空");

		// 将输入加密字符串转换成字节数组(utf8编码)
		byte[] byteArrayInput, byteArrayOutput;
		byteArrayInput = _value.getBytes("UTF-8");

		// md5加密，返回字节数组
		MessageDigest digest = MessageDigest.getInstance("MD5");
		digest.update(byteArrayInput);
		byteArrayOutput = digest.digest();

		// 返回字节数组的16进制表示
		String stringOutput = "";
		for (int i = 0; i < byteArrayOutput.length; i++) {
			String hex = Integer.toHexString(byteArrayOutput[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			//stringOutput += hex.toUpperCase() + " ";
			stringOutput += hex;
		}
		return stringOutput;
	}

	/**
	 * 字符串内容加密
	 * @param _records 字符串  
	 * @param _key 
	 * @return 返回 字符串数组,data[0]md5摘要,data[1]加密的字符串
	 * @throws NoSuchAlgorithmException
	 * @throws UnsupportedEncodingException
	 */
	private static String[] multiLineTextEncrypt(String _records, String _key) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		String[] temp = new String[2];
		// 参数检查
		if (StringUtils.isBlank(_records))
            System.out.println("传入加密的字符串不能为空");
		// 加入md5校验码
		 temp[0]= makeMD5Digest(_records);
		// 行记录异或加密
		 temp[1] = XorEncrypt(_records,_key);
		return temp;
	}

	private static String[] multiLineTextEncrypt(String _records) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		String[] temp = new String[2];
		// 参数检查
		if (StringUtils.isBlank(_records))
            System.out.println("传入加密的字符串不能为空");
		// 加入md5校验码
		 temp[0]= makeMD5Digest(_records);
		// 行记录异或加密
		 temp[1] = XorEncrypt(_records);
		return temp;
	}
	
	/**
	 * 字符串内容解密
	 * @param temp
	 * @return
	 * @throws IOException
	 * @throws NoSuchAlgorithmException
	 */
	private static String multiLineTextDecrypt(String temp) throws IOException, NoSuchAlgorithmException {
		String rest = null;
		// 参数检查
		if (StringUtils.isBlank(temp))
            System.out.println("未获取任何行内容");
		if(!StringUtils.isBlank(temp)){
			rest = XorEncrypt(temp);
		}
		return rest;
	}
	/**
	 * 加密字符串并生成base64字符串。
	 * 格式是:加密的字符串+md5摘要然后生成base64字符串
	 * @param key 
	 * @return 返回base64字符串
	 */
	public static String encryptString(String text, String key){
		String result =  "";
		try {
			String data[] = multiLineTextEncrypt(text,key);
			//加密的字符串+md5摘要然后生成base64字符串
			//result = new BASE64Encoder().encode((data[1]+data[0]).getBytes("UTF-8"));
			result = Base64.encodeBase64String((data[1]+data[0]).getBytes("UTF-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static String encryptString(String text){
		String result =  "";
		try {
			String data[] = multiLineTextEncrypt(text);
			//加密的字符串+md5摘要然后生成base64字符串
			//result = new BASE64Encoder().encode((data[1]+data[0]).getBytes("UTF-8"));
			result = Base64.encodeBase64String((data[1]+data[0]).getBytes("UTF-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 解密字符串
	 * @param text base64字符串，它的格式是:加密的字符串+md5摘要然后生成base64字符串
	 * @return 字符串数组 data[0]的值是success或error,data[1]成功时返回解决的字符串，错误时返回错误信息描述.实参非法返回null
	 */
	public static String[] decryptString(String text){
		String []result =  new String[2];
		if(null == text || "".equals(text)){
			return null;
		}
		try {
			//加密的字符串+md5摘要然后生成base64字符串
			//byte[] d = new BASE64Decoder().decodeBuffer(text);
			byte[] d = Base64.decodeBase64(text);
			
			
			String textStringAndMd5 = new String(d,"UTF-8");
			String textMD5 = "";
			if(null != textStringAndMd5 && 32 < textStringAndMd5.length()){
				//内容长度合法大于32位，因为md5摘要是32位
				//取密文数据内容
				String ciphertext = textStringAndMd5.substring(0, textStringAndMd5.length()-32);
				String plainText = multiLineTextDecrypt(ciphertext);
				String textMD5New = makeMD5Digest(plainText);
				textMD5 = textStringAndMd5.substring(textStringAndMd5.length()-32, textStringAndMd5.length());
				if(textMD5New.equals(textMD5)){
					//摘要验证通过
					result[0] = "success";
					result[1] = plainText;
				}else{
					//摘要验证失败
					result[0] = "error";
					result[1] = "md5 digest error.";
				}
			}else{
				result[0] = "error";
				result[1] = "BASE64Decode data's length is too short. It is "+textStringAndMd5.length();
			}
		} catch (Exception e) {
			result[0] = "error";
			result[1] = "occur an exception:"+e.getMessage();
			e.printStackTrace();
		}
		return result;
	}
	
	/*public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		*//*StringBuffer temp = new  StringBuffer("");
		String mm ="";
		temp.append(mm);
		System.out.println("----------------------生成加密的字符串------------------------------------------------------------------");
		System.out.println(encryptString(temp.toString()));
		
		String data = "ZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2U=";
		System.out.println("----------------------------解密字符串------------------------------------------------------------");
		System.out.println(decryptString(data)[0]);
		System.out.println(decryptString(data)[1]);*//*
		
		
	}*/

}
